open Base
open Math

type event = Tick | Click of Pos.t | Repaint | Exit

module type EVENTS_LAYER = sig
  type callback_id
  val bind_callback : (event -> unit) -> callback_id
  val unregister : callback_id -> unit
  val poll_time_ms : unit -> int
end

module type GRAPHICS_LAYER = sig
  val clear : unit -> unit
  val rect : AABB.t -> Color.t -> unit
end

(*
type 'id t =
  { mutable tree : Draw_tree.t
  ; mutable state : Source.State.t
  ; mutable callbacks : Component.Callbacks.t
  ; mutable event_cb_ids : 'id list }

module Make(E : EVENTS_LAYER)(G : GRAPHICS_LAYER) :
sig
  val run : Component.t -> unit
end
=
struct
  let poll_time _ =
    E.poll_time_ms () / 1000

  let apply t dispatch =
    let callbacks', state', upds = dispatch t.callbacks t.state in
    begin
      t.callbacks <- callbacks' ;
      t.state <- state' ;
      t.tree <- Draw_tree.apply_updates_exn upds t.tree ;
      not (Sequence.is_empty upds)
    end

  let handle_evt t =
    let open Component.Dispatch in
    function
    | Tick ->
       apply t
         (change Source.time ~f:poll_time)

    | Click(pos) ->
       apply t
         (Option.value_map (Draw_tree.capture_point ~pos t.tree)
            ~default:no_op
            ~f:(event @@ Event.Click(pos)))

    | Repaint ->
       true

    | Exit ->
       let () = List.iter ~f:E.unregister t.event_cb_ids in
       let () = t.event_cb_ids <- [] in
       false

  let repaint t =
    let () = G.clear () in
    Sequence.iter (Draw_tree.render t.tree)
      ~f:(function
          | Draw_tree.Draw.Rect(b, c) -> G.rect b c)

  let run app =
    let t =
      { tree = Draw_tree.uninit
      ; state = Source.State.of_time (poll_time ())
      ; callbacks = Component.Callbacks.empty
      ; event_cb_ids = [] }
    in
    let _ =
      apply t
        (Component.Dispatch.mount
           (Draw_tree.Path.root ())
           app)
    in
    let () =
      t.event_cb_ids <-
        [ E.bind_callback
            (fun ev -> if handle_evt t ev then repaint t) ]
    in
    repaint t

end
*)
